<?xml version="1.0"
      encoding="UTF-8"
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>IOP:实践之一</title>
<meta name="generator" content="http://txt2tags.sf.net" />
</head>
<body>

<div class="header" id="header">
<a name='toptopSkZIVkFPW' id='toptopSkZIVkFPW'></a><h1>IOP:实践之一</h1>
<h2>~ 如何令Python脚本提速100倍?!</h2>
</div>

<div class="toc" id="toc">
  <ol>
  <li><a href="#toc1R0VYQ0IyR">背景</a>
    <ul>
    <li><a href="#toc2R0VYRENMU">1.1. 预案</a>
    </li>
    </ul>
  </li>
  <li><a href="#toc3R0lYQ0FTS">IOP的加速技巧</a>
    <ul>
    <li><a href="#toc4R0lYRENMU">2.1. 10万:170+4秒</a>
      <ul>
      <li><a href="#toc5R0lYRENMU">2.1.1. code</a>
      </li>
      <li><a href="#toc6R0lYRENMU">2.1.2. speed</a>
      </li>
      <li><a href="#toc7R0lYRENMU">2.1.3. improve</a>
      </li>
      </ul>
    </li>
    <li><a href="#toc8R0lYREVMU">2.2. 10万:150+10秒</a>
      <ul>
      <li><a href="#toc9R0lYREVMU">2.2.1. thinking</a>
      </li>
      <li><a href="#toc10R0lYREVMU">2.2.2. code</a>
      </li>
      <li><a href="#toc11R0lYREVMU">2.2.3. improve</a>
      </li>
      </ul>
    </li>
    <li><a href="#toc12R0lYREdMU">2.3. 10万:100+200秒?!</a>
      <ul>
      <li><a href="#toc13R0lYREdMU">2.3.1. thinking</a>
      </li>
      <li><a href="#toc14R0lYREdMU">2.3.2. code</a>
      </li>
      <li><a href="#toc15R0lYREdMU">2.3.3. speed</a>
      </li>
      <li><a href="#toc16R0lYREdMU">2.3.4. improve</a>
      </li>
      </ul>
    </li>
    <li><a href="#toc17R0lYRElMU">2.4. 1000万:1100秒+480秒</a>
      <ul>
      <li><a href="#toc18R0lYRElMU">2.4.1. thinking</a>
      </li>
      <li><a href="#toc19R0lYRElMU">2.4.2. code</a>
      </li>
      <li><a href="#toc20R0lYRElMU">2.4.3. improve</a>
      </li>
      </ul>
    </li>
    <li><a href="#toc21R0lYREtMU">2.5. 小记</a>
    </li>
    </ul>
  </li>
  <li><a href="#toc22R01YQ0JaV">提速100倍</a>
  </li>
  </ol>

</div>
<div class="body" id="body">
<a id="toc1R0VYQ0IyR" name="toc1R0VYQ0IyR"></a>
<h1><A href='#toptopSkZIVkFPW'> 1. 背景 </A></h1>
<p>
什么事儿呢?
</p>
<ul>
<li>在一高压力服务环境中,需要加速系统的响应
</li>
<li>现行系统对于数据查询要尝试三种数据库源:
 <ol>
 <li>memcache
 </li>
 <li>redis
 </li>
 <li>MySQL
 </li>
 </ol>
</li>
<li>期望查询加速至少 300%
</li>
</ul>

<dl>
<dt>运行环境</dt><dd>
<pre>
客户机:
    - 俺的Laptop HP 520
    - 双核CPU 2G内存
    - Ubuntu 9.10
DB主机:
    - CentOS 5.0
    - 单核CPU 4G 内存
</pre>
</dd>
</dl>

<a id="toc2R0VYRENMU" name="toc2R0VYRENMU"></a>
<h2><A href='#toptopSkZIVkFPW'> 1.1. 预案 </A></h2>
<p>
这事儿,一想,简单哪,都放内存就好的哪
</p>
<ul>
<li>统计了一下需要用来查询的数据不到2千万条
</li>
<li>折算成文件不过1G
</li>
<li>加载到内存中,使用 Python 字典结构的话,也最多涨一倍,也完全可以接受
</li>
<li>速度?!
 <ul>
 <li><a href="http://yongsun.me/2007/11/python-rbtree%e5%92%8c%e5%86%85%e5%bb%badict%e7%9a%84%e6%80%a7%e8%83%bd%e6%af%94%e8%be%83/">python-rbtree和内建dict的性能比较</a>
 </li>
 <li>那绝对不是问题!
 </li>
 </ul>
</li>
</ul>

<a id="toc3R0lYQ0FTS" name="toc3R0lYQ0FTS"></a>
<h1><A href='#toptopSkZIVkFPW'> 2. IOP的加速技巧 </A></h1>
<p>
<code>没有想到,加速,只要不断将代码住短里面写就好!</code>
</p>
<p>
不知道什么是 IOP?
</p>
<ul>
<li><a href="http://wiki.woodpecker.org.cn/moin/PyIOP">PyIOP</a>
</li>
<li>咔咔咔,沈游侠总结的编程态度&gt;...
</li>
</ul>

<a id="toc4R0lYRENMU" name="toc4R0lYRENMU"></a>
<h2><A href='#toptopSkZIVkFPW'> 2.1. 10万:170+4秒 </A></h2>
<dl>
<dt>最直接的实现</dt><dd>
</dd>
</dl>

<ul>
<li>从redis 读
</li>
<li>生成 dict 对象
</li>
<li>以pickle dump 出序列化文件
</li>
<li>用pickle load 加载成dict对象
</li>
</ul>

<a id="toc5R0lYRENMU" name="toc5R0lYRENMU"></a>
<h3><A href='#toptopSkZIVkFPW'> 2.1.1. code </A></h3>
<dl>
<dt>代码:</dt><dd>
<p></p>
<pre class="brush:  python">

#!/usr/bin/python 
# -*- coding: utf-8 -*-
import struct,sys,time
import cPickle as pickle
import redis
REVERSION = "r2d.py v10.5.7"
def _push2dict(dictall,key,smembers):
    dictall[struct.pack('I',int(key[1:]))]=[s.split("|") for s in rb.smembers(k)]    
    return dictall
if __name__ == '__main__':      # this way the module can be
    if 3 != len(sys.argv):
        print """ %s usage::
$ python r2d.py redistIP limitnumber [like 10000]
        """ % REVERSION
    else:
        hostIP = sys.argv[1]
        limitn = sys.argv[2]
        rb = redis.Redis(host=hostIP, port=6379, db=9)
        rbkeys = rb.keys().split()
        loop = int(limitn)
        s4dict={}
        for k in rbkeys:
            if 0 == loop:
                break
            else:
                loop -=1
                _push2dict(s4dict,k,rb.smembers(k))
        pickle.dump(s4dict, open('r4d.dump', 'wb'))
</pre>
</dd>
</dl>

<a id="toc6R0lYRENMU" name="toc6R0lYRENMU"></a>
<h3><A href='#toptopSkZIVkFPW'> 2.1.2. speed </A></h3>
<ul>
<li>代码足够简单了,单函式,20行
</li>
<li>速度测试::
 <ul>
 <li>10W 值对导出 &gt;170秒,导入&gt;4秒;
 </li>
 <li>100W 值对导出 &gt;500秒,导入&gt;25秒;
 </li>
 <li>1000W 值对导出 <b>失败! 内存提前耗光!</b>
 </li>
 </ul>
</li>
</ul>

<a id="toc7R0lYRENMU" name="toc7R0lYRENMU"></a>
<h3><A href='#toptopSkZIVkFPW'> 2.1.3. improve </A></h3>
<p>
这完全无法接受哪...
</p>
<dl>
<dt>加速尝试::</dt><dd>
</dd>
</dl>

<ol>
<li>根据 IOP 尽量不用函式,将那个一行函式清除,代码填回循环 ~ <i>立即获得几秒的加速</i>
</li>
<li>本来用的就是cPickle 了,模块效率没有办法了
</li>
<li>嗯嗯嗯,可以不用 cPickle卟?
 <ul>
 <li>直接输出自然 .py 哈?!
 </li>
 </ul>
</li>
</ol>

<pre class="brush:  python">


# 使用 str() 将字典对象用文本的方式记入 .py 
vdf = open("r2d.define.py","wa")
vdf.write("s4dict=")
vdf.write(str(s4dict))
vdf.close()
# 使用时直接 import 就好

</pre>
<p></p>
<ul>
<li>改进后测试::
 <ul>
 <li>10W 值对导出 &gt;160秒,导入&gt;3秒;
 </li>
 <li>100W 值对导出 &gt;400秒,导入&gt;19秒;
 </li>
 <li>1000W 值对导出 <b>依然杯具</b>
 </li>
 </ul>
</li>
<li>加速不明显:
 <ul>
 <li>导出时速度变化很小
 </li>
 <li>载入时速度有提升
 </li>
 </ul>
</li>
<li>进一步观察到,导出时内存飞速增长:
 <ul>
 <li>100W级别,要食掉1.6G左右的内存
 </li>
 <li>redis 本身也很占内存,千万级别时,也要占上G (当然这和条目数量/内容有关)
 </li>
 <li>这对于服务器是个不可接受的方式
 </li>
 </ul>
</li>
</ul>

<a id="toc8R0lYREVMU" name="toc8R0lYREVMU"></a>
<h2><A href='#toptopSkZIVkFPW'> 2.2. 10万:150+10秒 </A></h2>
<dl>
<dt>改进中间数据格式:</dt><dd>
</dd>
</dl>

<ul>
<li>从redis 读
</li>
<li>生成 中间log文件
</li>
<li>导入成 字典对象
</li>
</ul>

<a id="toc9R0lYREVMU" name="toc9R0lYREVMU"></a>
<h3><A href='#toptopSkZIVkFPW'> 2.2.1. thinking </A></h3>
<p>
因为有这些现实:
</p>
<ol>
<li>想输出不论 pickle 或是 .py 的字典对象,都得先在内存中构造出这一对象
</li>
<li>随着字典对象的规模增加,必然导致这一构建过程的时间加长
</li>
</ol>

<p>
经沈游侠提醒,发现字典对象其实是可以线性输出的:
</p>
<ul>
<li>比如说,字典结构如:
<pre>
{key:[(v1,v2,v3),..]
,...
}
</pre>
 <ul>
 <li><code>K:[list]</code> 形式的两层结构
 </li>
 </ul>
</li>
<li>那么,就可以通过中间数据文本:
<pre>
('key', [(v1, 'v2', v3)])
...
</pre>
</li>
<li>进行线性加载,e.g:
<pre class="brush:  python">

for l in open("r2d.define.py.log","r").readlines():
    dd = eval(l)
    if dd[0] in s4d:
        s4d[dd[0]].append((dd[1],dd[2],dd[3]))
    else:
        s4d[dd[0]]=[(dd[1],dd[2],dd[3])]

</pre>
</li>
</ul>

<a id="toc10R0lYREVMU" name="toc10R0lYREVMU"></a>
<h3><A href='#toptopSkZIVkFPW'> 2.2.2. code </A></h3>
<p>
快速修订对应行动代码:
</p>
<pre class="brush:  python">

#!/usr/bin/python 
# -*- coding: utf-8 -*-
import struct,sys,time
import redis
REVERSION = "r2d.py v10.5.8"
if __name__ == '__main__':      # this way the module can be
    if 3 != len(sys.argv):
        print """ %s usage::
$ python r2d.py redistIP limitnumber [like 10000] &gt; mid-data.log
        """ % REVERSION
    else:
        hostIP = sys.argv[1]
        limitn = sys.argv[2]
        rb = redis.Redis(host=hostIP, port=6379, db=9)
        rbkeys = rb.keys().split()
        loop = int(limitn)
        for k in rbkeys:
            if 0 == loop:
                break
            else:
                loop -=1
                dictkey = struct.pack('I',int(k[1:]))
                sli = []
                for s in rb.smembers(k):
                    rli = s.split("|")[:3]
                    if rli:
                        rli[0] = int(rli[0])
                        rli[1] = struct.pack('I',int(rli[1]))
                        rli[2] = int(rli[2])
                        sli.append(tuple(rli))
                print &gt;&gt; d2f,`dictkey,sli`
                #注意: `obj` 等同 repr(obj)  
</pre>
<p></p>
<a id="toc11R0lYREVMU" name="toc11R0lYREVMU"></a>
<h3><A href='#toptopSkZIVkFPW'> 2.2.3. improve </A></h3>
<p>
代码依然简单了,无函式,30行
</p>
<ul>
<li>速度测试::
 <ul>
 <li>10W 值对导出 &gt;150秒,导入&gt;10秒;
 </li>
 <li>100W 值对导出 &gt;500秒,导入&gt;20秒;
 </li>
 <li>1000W 值对导出 &gt;1300秒,导入&gt;90秒;
 </li>
 </ul>
</li>
<li>速度看起来没有什么明显的提高
</li>
<li><b>不过!</b>
 <ol>
 <li>千万级别的数据可以在低配置环境中跑完了!
 </li>
 <li>内存占用很稳定永远90M左右,不会随字典对象的增长而增长!
 </li>
 </ol>
</li>
</ul>

<p>
嗯嗯嗯,这算是可用了...
</p>
<a id="toc12R0lYREdMU" name="toc12R0lYREdMU"></a>
<h2><A href='#toptopSkZIVkFPW'> 2.3. 10万:100+200秒?! </A></h2>
<dl>
<dt>继续改进:</dt><dd>
</dd>
</dl>

<ul>
<li>放弃 redis 直接从MySQL 读
</li>
<li>生成 中间日志
</li>
<li>导入成 dict 文件
</li>
</ul>

<a id="toc13R0lYREdMU" name="toc13R0lYREdMU"></a>
<h3><A href='#toptopSkZIVkFPW'> 2.3.1. thinking </A></h3>
<p>
虽然redis 是号称最快的 K/V 数据库产品，但是，明显就是它将整个业务响应速度拖慢了..
</p>
<dl>
<dt>为什么呢？</dt><dd>
</dd>
</dl>

<ul>
<li>服务器程序和本地程序面对的环境是不同的
</li>
<li>高压力服务器程序和小压力服务器程序也是不同的
</li>
<li>简单来说:
 <ol>
 <li>小型服务~=每秒&lt;C60
 </li>
 <li>中型服务~=每秒&lt;C600
 </li>
 <li>大型服务~=每秒&gt;C1000
 </li>
 </ol>
</li>
<li>面对的矛盾是完全不同的:
 <ol>
 <li>小型服务-&gt;语言执行效率
 </li>
 <li>中型服务-&gt;框架执行效率
 </li>
 <li>大型服务-&gt;I/O 响应速度
 </li>
 </ol>
</li>
<li>所以，对于面向Web 的查询服务，不论 Redis/MySQL 对于业务系统，都是进程间通讯!
</li>
<li>每次跨进程通讯，都意味着至少四次I/O操作！
</li>
<li>所以，当前 Redis-&gt;log-&gt;内存字典的转换流程，其实包含了 MySQL-&gt;Redis 的进程操作
</li>
<li>另外:
 <ul>
 <li>遍查 Redis 文档，居然没有 <code>iterkeys()</code> 类似的操作！
 </li>
 <li>每次不论转换多少 Redis 的值对，都得使用<code>keys()</code> 将键先取出来然后再逐一匹配处理
 </li>
 <li>怪不得使用 Redis 测试用小仓库(包含20万值对)时，脚本运行速度和使用全数据Redis(千万值对)时速度要相差5倍以上！内存也占用多几倍!
 </li>
 </ul>
</li>
</ul>

<p>
<b>所以!要直接从 MySQL 相关表中读取</b>
</p>
<a id="toc14R0lYREdMU" name="toc14R0lYREdMU"></a>
<h3><A href='#toptopSkZIVkFPW'> 2.3.2. code </A></h3>
<p>
配合一SQL 模板:
</p>
<pre class="brush:  sql">

-- _tpl/all_black.tpl
SELECT v1,v2,v3,v4,id FROM t_black LIMIT %(limitMAX)s;
</pre>
<p></p>
<p>
核心代码:
</p>
<pre class="brush:  python">

#!/usr/bin/python 
# -*- coding: utf-8 -*-
REVERSION = "m2d.py v10.5.9"
import struct,sys,time

if __name__ == '__main__':      # this way the module can be
    """usage:
$ python m2d.py limit [such as 100] |\
  mysql -h xx.xx.xx.xx -u User -D --password=***  |\
  python m2d.py &gt; m2d.log
    """
    if sys.stdin:
        if 1 &lt; len(sys.argv):
            limit = sys.argv[1]
            limitMAX = int(limit)
            print &gt;&gt; sys.stderr, info
            print open("_tpl/all_black.tpl","r").read()%locals()
        else:
            s4dict={}
            virusname={}
            totalN = 0
            for l in sys.stdin.readlines():
                if "id" in l:
                    pass
                else:
                    totalN += 1
                    lkv=l.split()
                    dictkey = struct.pack('I',int(lkv[0]))
                    lkv[1] = int(lkv[1])
                    lkv[2] = struct.pack('I',int(lkv[2]))
                    lkv[3] = int(lkv[3])
                    print &gt;&gt; d2f,`dictkey,tuple(lkv[1:])`
</pre>
 <ul>
 <li>用是否有额外参数来判定是否生成SQL,还是进行MySQL 的输出数据处理
 </li>
 <li>为了不影响标准输出,调试信息,输出到标准错误IO
 </li>
 <li>调试也应该根据管道串的层级,一级级运行尝试
 </li>
 <li>调用的shell:
<pre class="brush:  shell">

#!/bin/sh
#   m2d.sh v10.5.9
python m2d.py go |\
    mysql -h xx.xx.xx.xx -u User --password=***|\
    python mysql4dict.py $1 |\
    mysql -h xx.xx.xx.xx -u User --password=***|\
    python m2d.py &gt; m2d.log
</pre>
 <p></p>
<b>加载时代码没有怎么变</b>
 </li>
 </ul>

<a id="toc15R0lYREdMU" name="toc15R0lYREdMU"></a>
<h3><A href='#toptopSkZIVkFPW'> 2.3.3. speed </A></h3>
<ul>
<li>速度测试::
 <ul>
 <li>0.1W 值对导出 &lt;5秒,导入&lt;1秒;
 </li>
 <li>10W 值对导出 &gt;300秒,导入&gt;10秒;
 </li>
 <li>100W 值对导出 杯具鸟
 </li>
 <li>1000W 值对导出 杯具鸟
 </li>
 </ul>
</li>
<li>速度怎么和查询的条目多少有关? 而且一大MySQL 就拒绝服务?
</li>
</ul>

<a id="toc16R0lYREdMU" name="toc16R0lYREdMU"></a>
<h3><A href='#toptopSkZIVkFPW'> 2.3.4. improve </A></h3>
<p>
嗯嗯嗯,FT! 当然了,MySQL 请求响应时间是有限制的,大数据传输肯定是有问题的,
利用 <code>LIMIT</code> 的切片!
</p>
<ul>
<li>改造前述<code>m2d.py v10.5.9</code> SQL生成部分的代码:
<pre class="brush:  python">

step = 5000.0
limitMAX = int(limit)
sqltpl = open("_tpl/all_black.tpl","r").read()
if 1 &gt;= limitMAXb/step:
    print sqltpl%locals()
else:
    for i in range(int(limitMAX/step)):
        limitMAX = "%d,%d"%(step*i,int(step))
        print sqltpl%locals()
</pre>
</li>
<li>以 5000 为界限,生成类似 <code>LIMIT 15000,5000</code> 的限制
</li>
</ul>

<ul>
<li>速度测试::
 <ul>
 <li>100W 值对导出 &gt;290秒,导入&gt;190秒;
 </li>
 <li>1000W 值对导出 杯具鸟
 </li>
 </ul>
</li>
</ul>

<p>
<b>FT!怎么回事儿?速度意外的慢!</b>
</p>
<a id="toc17R0lYRElMU" name="toc17R0lYRElMU"></a>
<h2><A href='#toptopSkZIVkFPW'> 2.4. 1000万:1100秒+480秒 </A></h2>
<dl>
<dt>冷静后改进:</dt><dd>
</dd>
</dl>

<ul>
<li>从MySQL 读使用id 进行限制切分
</li>
<li>生成 中间日志,但是重新设计结构
</li>
<li>导入成 dict 文件
</li>
</ul>

<a id="toc18R0lYRElMU" name="toc18R0lYRElMU"></a>
<h3><A href='#toptopSkZIVkFPW'> 2.4.1. thinking </A></h3>
<dl>
<dt>MySQL 为什么这么慢?!</dt><dd>
</dd>
</dl>

<ul>
<li>嗯嗯嗯,N久没有使用过DB,这次重温了为什么远离DB的恶体验
</li>
<li>MySQL 本身就不是千万级别的产品,虽然有很多招可以应对
 <ul>
 <li><a href="http://www.cnblogs.com/fjytzh/archive/2010/04/02/1702886.html">mysql limit查询优化（数据量大的时候很优）</a>
 </li>
 <li><a href="http://grb12508.blog.163.com/blog/static/273784582009102448061/">Mysql limit 优化，百万至千万级快速分页</a>
 </li>
 </ul>
</li>
<li>不过,以上招都不好使,咨询了一下同事,直接使用ID范畴来限定就好!
</li>
</ul>

<a id="toc19R0lYRElMU" name="toc19R0lYRElMU"></a>
<h3><A href='#toptopSkZIVkFPW'> 2.4.2. code </A></h3>
<p>
SQL 模板配合改进:
</p>
<pre class="brush:  sql">

-- _tpl/all_black.tpl
SELECT v1,v2,v3,v4,id FROM t_black WHERE id&gt;%(LIMbwID)s AND id&lt;=%(MAXbwID)s;
</pre>
<p></p>
<p>
SQL 生成代码:
</p>
<pre class="brush:  python">

step = 3000.0
offset = int(step)
# &lt; &lt;gen_sql_with_max&gt; &gt; 使用Leo 时可以定义子节点将成堆代码变成语义标记
for l in sys.stdin.readlines():
    if "max(id)" not in l:
        amount = l.split()
        MAXbwID = int(amount[0]
        MINbwID = int(amount[1]
        MAXbwA = MAXbID-MINbID
MAXbMAX = MAXbwID
lastID = 0
sqltpl = open("_tpl/all_black.tpl","r").read()
for i in range(MAXbwA/offset):
    MAXbwID,LIMbwID = (MAXbMAX-offset*i,MAXbMAX-offset*(i+1))
    print sqltpl%locals()
    lastID = LIMbID
MAXbID,LIMbID = lastID,MINbID   # 将切片限数之内的尾数个ID也查询出来
print sqltpl%locals()
</pre>
<ul>
<li>咔咔咔,当然的,要进行基于ID 的精确切分选择,就得先知道最大和最小的ID
</li>
<li>使用SQL <code>SELECT max(id),min(id) FROM t_black ;</code>
</li>
<li>自然运用系统管道串接成处理过程:
<pre class="brush:  shell">

#!/bin/sh
#   m2d.sh v10.5.9
DATE=`date "+%y%m%d-%H%M%S"`
mysql -h xx.xx.xx -u User --password=*** &lt; _tpl/total_black.sql |\
    python m2d.py go |\
    mysql -h xx.xx.xx -u User --password=*** |\
    python m2d.py &gt; m2d_$DATE.log
</pre>
</li>
</ul>

<a id="toc20R0lYRElMU" name="toc20R0lYRElMU"></a>
<h3><A href='#toptopSkZIVkFPW'> 2.4.3. improve </A></h3>
<ul>
<li>速度测试::
 <ul>
 <li>100W 值对导出 &gt;280秒,导入&gt;120秒;
  <ul>
  <li>m2d.log &gt; 150M
  </li>
  </ul>
 </li>
 <li>1000W 值对导出 &gt;1300秒,导入&gt;780秒;
  <ul>
  <li>m2d.log &gt; 570M
  </li>
  </ul>
 </li>
 </ul>
</li>
</ul>

<p>
进一步的,发现业务其实可以将双层,两次查询优化成一次查询的!
</p>
<ul>
<li>简单的将输出字典的数据结构变成:
<pre>
{key:v,...
}
</pre>
</li>
<li>将原先的2个值结合原先的key 变成键,就成为了全局唯一的key
</li>
<li>即和MySQL 每行数据完成一一对应
</li>
<li>速度再测试::
 <ul>
 <li>100W 值对导出 &gt;250秒,导入&gt;100秒;
  <ul>
  <li>m2d.log &gt; 130M
  </li>
  </ul>
 </li>
 <li>1000W 值对导出 &gt;1100秒,导入&gt;480秒;
  <ul>
  <li>m2d.log &gt; 490M
  </li>
  </ul>
 </li>
 </ul>
</li>
<li>哗! 而且加载完后,字典对象所点内存体积也同样减少了 30% !
</li>
</ul>

<a id="toc21R0lYREtMU" name="toc21R0lYREtMU"></a>
<h2><A href='#toptopSkZIVkFPW'> 2.5. 小记 </A></h2>
<dl>
<dt>综上:</dt><dd>
</dd>
</dl>

<ul>
<li>应用 IOP 方面的主要招术:
 <ol>
 <li>表用 函式
 </li>
 <li>表用 模块
 </li>
 <li>尽量使用 OS 的标准 I/O 进行功能串接
 </li>
 </ol>
</li>
<li><b>DOP</b>~<code>Data Oriented Programming</code>
 <ul>
 <li>面向数据编程
 </li>
 <li>归根到底,程序都得操作数据解决问题
 </li>
 <li>服务器端,大并发压力时,最有效的节省I/O 的方式,就是高效方式
 </li>
 <li>压缩输入/出的数据量自然是最好的代码!
 </li>
 </ul>
</li>
</ul>

<a id="toc22R01YQ0JaV" name="toc22R01YQ0JaV"></a>
<h1><A href='#toptopSkZIVkFPW'> 3. 提速100倍 </A></h1>
<p>
嗯嗯嗯？！怎么说到最后好象也没有加速到100倍哪？
</p>
<ul>
<li>是也乎，是也乎，以上分享的是内存化字典数据的转换脚本加速过程
</li>
<li>但是最后要加速的是整个查询业务哈?
</li>
<li>因为涉及公司核心服务,代码就无法展示了
</li>
<li>不过,现实是:
 <ol>
 <li>使用了以上 IOP 中提及的基础技巧
 </li>
 <li>每查询业务的处理时间从原先的 0.* 秒,加速到 0.00*秒,至少100倍
 </li>
 <li>而对应的代码从 几千行,精简到几十行
 </li>
 </ol>
</li>
</ul>

<p>
所以,基本上可以这么理解:
</p>
<ul>
<li>将代码每<b>精简一倍体积</b>
</li>
<li>运行速度就有望<b>提高10倍</b>
<p></p>
不相信? 尝试一哈噻...
</li>
</ul>

<hr class="light" />
<ul>
<li>t2t渲染:: 2010-10-09 02:21:36
</li>
<li>动力源自::<b><a href="http://txt2tags.sf.net">txt2tags</a></b>
</li>
</ul>

</div>

<!-- xhtml code generated by txt2tags 2.4 (http://txt2tags.sf.net) -->
<!-- cmdline: txt2tags ./Zen/IOP/iop-how2-tenfold-speed-py-script-2010-05-13-19-19.t2t -->
</body></html>
